package com.wufun.baselibrary.download;

import android.app.DownloadManager;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.text.TextUtils;

import com.wufun.baselibrary.utils.FileUtils;
import com.wufun.baselibrary.utils.LogUtils;
import com.wufun.baselibrary.utils.StringUtils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by lala on 2017/3/18.
 * 通用下载模块，只做下载操作
 */

public class CommonDownloadTask implements Runnable {
    public final static int STATUS_NORMAL = 0;
    public final static int STATUS_FINISH = 1;
    public final static int STATUS_STOP = 3;
    public final static int STATUS_ERROR = 4;
    public final static int STATUS_PROGRESS = 5;
    public final static int STATUS_STSRT_ZIP = 6;
    public final static int STATUS_ZIP_PROGRESS = 7;
    public final static int STATUS_ZIP_FAIL = 8;
    public final static int STATUS_START = 2;
    public final static int STATUS_SIZE = -1;
    public final static int STATUS_NOT = -2;

    private AtomicBoolean stopFlag = new AtomicBoolean(false);
    private Handler handler;
    int tryCount = 3;
    private long expectSize;//期望的文件大小
    private long actualSize;//服务器返回的实际文件大小
    private String url;
    private String fileName;
    private String gameName;
    private String downloadPath;
    private File file;

    private HttpURLConnection connection;
    private HttpURLConnection connection1;
    private RandomAccessFile out = null;
    private InputStream in = null;

    private long curSize;

    public CommonDownloadTask(String url, String fileName, String downloadPath, String gameName) {
        this.url = url;
        this.fileName = fileName;
        this.downloadPath = downloadPath;
        this.gameName = gameName;
    }

    private void readData(long curSize) throws IOException {

        int bs=4096;
        byte[] buffer = new byte[bs];
        int nRead = 0;
        long startTime = System.currentTimeMillis();
        long tempSize = curSize;

        while ((nRead = in.read(buffer, 0, bs)) > 0) {

            if(stopFlag.get()){
                //中止下载
                stop();
                break;
            }

            out.write(buffer, 0, nRead);
            this.curSize += nRead;
            long now = System.currentTimeMillis();
            long gap = now-startTime;
            if(gap>500){
                //todo 发送下载进度
                speed = UtilsMy.FormatFileSizeForSpeed(1000 * (this.curSize -tempSize) / gap);
                LogUtils.e(">>>tbl:"+speed+" ..... "+(1000 * (this.curSize -tempSize) / gap));
                long a = (this.curSize *100)/actualSize;
                percent = (a)+"";
                LogUtils.e(">>>tbl:"+a+" ..... "+a);
                sendMsg(STATUS_PROGRESS);
                startTime = now;
                tempSize = this.curSize;
                LogUtils.e(">>>tbl:"+tempSize+" ..... "+tempSize);
            }

        }
    }

    private void stop() {
        close();
        sendMsg(STATUS_STOP);
    }

    String speed;
    String percent;

    @Override
    public void run() {

        Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);

        if (StringUtils.isEmpty(url)) {
            //todo 发送任务url无效通知
            sendMsg(STATUS_ERROR);
            return ;
        }

        FileUtils.makeDirs(downloadPath);
        file = new File(downloadPath+fileName);
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                LogUtils.e(">>>>>tbl>e:"+e.getMessage());
                //todo 发送文件创建失败通知
                sendMsg(STATUS_ERROR);
                return ;
            }
        }
        if(stopFlag.get()){
            stop();
            return;
        }
        while (tryCount > 0) {
            long range = 0;
            if (file.exists()) range = file.length();

            try {
                URL netUrl = new URL(url);
                //只读取头信息获取文件总大小，用来识别是否是真正的要下载的目标文件
                connection = (HttpURLConnection) netUrl.openConnection();
                connection.setConnectTimeout(3000);
                connection.setReadTimeout(3000);
                connection.setRequestProperty("Connection", "Keep-Alive");
                connection.setRequestMethod("GET");
                int status = connection.getResponseCode();
                if (status == HttpURLConnection.HTTP_OK) {
                    String contentType = connection.getHeaderField("Content-Type");
                    if (StringUtils.isEmpty(contentType)) contentType = "";
                    contentType = contentType.toLowerCase();

                    if (contentType.equals("application/octet-stream") || contentType.equals("application/vnd.android.package-archive") || contentType.equals("application/zip") || expectSize == connection.getContentLength()) {
                        if(expectSize!=0){
                            if(expectSize != connection.getContentLength()){
                                connection.disconnect();
                                tryCount--;
                                continue;
                            }
                        }
                        actualSize = connection.getContentLength();

                        LogUtils.e("tbl>>>>>>expectSize:"+ expectSize+", actualSize:"+actualSize);
                        sendMsg(STATUS_SIZE);
                        if(range==actualSize){
                            //todo 发送下载成功通知
//                            File file = new File(downloadPath+fileName);
//                            if (file.exists()) {
//                                sendMsg(STATUS_STSRT_ZIP);
//                                boolean bs= Xzip.upZipFile(new File(downloadPath+fileName), downloadPath
//                                        , this.url, new zipListener());
//                                LogUtils.e("tbl>>>>>:bs:"+ bs);
//                                if (bs==true){
//                                    sendMsg(STATUS_FINISH);
//                                } else {
//                                    sendMsg(STATUS_ZIP_FAIL);
//                                }
//                            } else {
//                                sendMsg(STATUS_ERROR);
//                            }

                            close();
                            return ;
                        }
                    }else{
                        connection.disconnect();
                        tryCount--;
                        continue;
                    }
                }else{
                    connection.disconnect();
                    tryCount--;
                    continue;
                }

                new Thread() {//关闭流
                    @Override
                    public void run() {
                        super.run();
                        if (connection != null) {
                            connection.disconnect();
                            connection = null;
                        }
                    }
                }.start();
                if(stopFlag.get()){
                    stop();
                    return;
                }
                //正式开始下载
                connection1 = (HttpURLConnection) netUrl.openConnection();
                connection1.setConnectTimeout(3000);
                connection1.setReadTimeout(3000);
                connection1.setRequestProperty("Connection", "Keep-Alive");
                connection1.setRequestMethod("GET");
                if (range > 0) {//断点续传
                    connection1.setRequestProperty("Range", "bytes=" + range + "-");
                }

                status = connection1.getResponseCode();
                boolean success;
                switch (status) {
                    case HttpURLConnection.HTTP_OK:
                    case HttpURLConnection.HTTP_PARTIAL:
                        String transfer_encoding = connection1.getHeaderField("Transfer-Encoding");
                        if (!TextUtils.isEmpty(transfer_encoding)
                                && transfer_encoding.equalsIgnoreCase("chunked")) {
                        }
                        if (status == HttpURLConnection.HTTP_OK && range > 0) {//网络不支持断点续传，则要删除文件重新下载
                            if (file.exists()) UtilsMy.delete(file);
                        }
                        success = true;
                        break;
                    case HttpURLConnection.HTTP_MOVED_TEMP:
                    case HttpURLConnection.HTTP_MOVED_PERM:
                    case HttpURLConnection.HTTP_SEE_OTHER:
                        success = false;
                        break;
                    default:
                        success = false;
                        break;
                }
                if(!success){
                    new Thread() {//关闭流
                        @Override
                        public void run() {
                            super.run();
                            if (connection1 != null) {
                                connection1.disconnect();
                                connection1 = null;
                            }
                        }
                    }.start();
                    if(tryCount==0)sendMsg(STATUS_ERROR);
                    continue;
                }

                String contentTypeConnection = connection1.getHeaderField("Content-Type");
                if (StringUtils.isEmpty(contentTypeConnection)) contentTypeConnection = "";
                contentTypeConnection = contentTypeConnection.toLowerCase();
                if (contentTypeConnection.equals("application/octet-stream") || contentTypeConnection.equals("application/vnd.android.package-archive") || contentTypeConnection.equals("application/zip") || expectSize == connection.getContentLength()) {

                } else {
                    connection1.disconnect();
                    continue;
                }

                out = new RandomAccessFile(file, "rw");
                out.seek(range);
                curSize = range;
                in = new BufferedInputStream(connection1.getInputStream());
                readData(curSize);
                break;
            } catch (Exception e) {
                e.printStackTrace();
                tryCount--;
                if(tryCount==0){
                    //todo 发送下载失败通知
                    sendMsg(STATUS_ERROR);
                }
            }finally {

                if(file.length() == actualSize){
                    try {
                        File file = new File(downloadPath+fileName);
                        if (file.exists()) {
                            sendMsg(STATUS_STSRT_ZIP);
                            boolean bs= Xzip.upZipFile(new File(downloadPath+fileName), downloadPath);
                            LogUtils.e("tbl>>>>>:bs2:"+ bs);
                            if (bs==true){
                                //todo 发送下载完成通知
                                sendMsg(STATUS_FINISH);
                            } else {
                                sendMsg(STATUS_ZIP_FAIL);
                            }
                        } else {
                            sendMsg(STATUS_ERROR);
                        }
                    } catch (Exception e) {
                        LogUtils.e("tbl>>>>>:e:"+ e.getMessage());
                        sendMsg(STATUS_ERROR);
                    }
                    close();
                    break;
                }
            }

        }
        return ;
    }

    private void close() {

        try {
            if(connection!=null){
                connection.disconnect();
            }
        }catch (Exception e){}

        try {
            if (in != null) {
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (out != null) {
            try {
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (connection1 != null) {
            try {
                connection1.disconnect();
                connection1 = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public long getExpectSize() {
        return expectSize;
    }

    public void setExpectSize(long expectSize) {
        this.expectSize = expectSize;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getDownloadPath() {
        return downloadPath;
    }

    public void setDownloadPath(String downloadPath) {
        this.downloadPath = downloadPath;
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }

    public String getGameName() {
        return gameName;
    }

    public void setGameName(String gameName) {
        this.gameName = gameName;
    }

    public void cancel() {
        this.stopFlag.set(true);
    }

    private void sendMsg(int status){
        Message msg = Message.obtain();
        msg.what = status;
        if(status==STATUS_PROGRESS)
            msg.obj = url+";"+speed+";"+percent;
        else if (status == STATUS_ERROR)
            msg.obj = url+";"+gameName;
        else if (status == STATUS_FINISH)
            msg.obj = url+";"+gameName;
        else if (status == STATUS_SIZE)
            msg.obj = url+";"+actualSize;
        else
            msg.obj = url+";"+gameName;
        handler.sendMessage(msg);
    }
}
